﻿package frEngine.core
{
    import __AS3__.vec.*;
    import flash.display3D.*;
    import flash.utils.*;

    public class FrVertexBuffer3D extends Object
    {
        public var sizePerVertex:int = 0;
        public var bufferVoMap:Dictionary;
        public var vertexBuffer:VertexBuffer3D;
        private var _needUpdate:Boolean = true;
        private var _parentFrSurface:FrSurface3D;
        private var _vertexVector:Vector.<Number>;
        private var _vertexBytes:ByteArray;
        public var isSingle:Boolean;

        public function FrVertexBuffer3D(param1:FrSurface3D, param2:Boolean)
        {
            this.bufferVoMap = new Dictionary(false);
            this._parentFrSurface = param1;
            this.isSingle = param2;
            return;
        }// end function

        final public function get needUpdate() : Boolean
        {
            return this._needUpdate;
        }// end function

        public function set vertexBytes(param1:ByteArray) : void
        {
            if (param1 == this._vertexBytes)
            {
                return;
            }
            if (this._vertexBytes)
            {
                this._vertexBytes.clear();
            }
            this._vertexBytes = param1;
            return;
        }// end function

        public function clone(param1:FrSurface3D) : FrVertexBuffer3D
        {
            var _loc_2:* = new FrVertexBuffer3D(param1, this.isSingle);
            _loc_2.bufferVoMap = this.bufferVoMap;
            _loc_2.sizePerVertex = this.sizePerVertex;
            _loc_2._vertexVector = this._vertexVector;
            _loc_2._vertexBytes = this._vertexBytes;
            return _loc_2;
        }// end function

        public function toUpdate() : void
        {
            this._needUpdate = true;
            if (this._parentFrSurface)
            {
                this._parentFrSurface.toUpdate();
            }
            return;
        }// end function

        public function canInsert(param1:int, param2:int) : Boolean
        {
            var _loc_4:Boolean = false;
            var _loc_5:int = 0;
            if (this.sizePerVertex > 0 && this.isSingle)
            {
                return false;
            }
            var _loc_3:* = "float" + param2;
            if (this.bufferVoMap[param1] != null)
            {
                _loc_5 = int(this.bufferVoMap[param1].size);
                _loc_4 = this.sizePerVertex - _loc_5 + param2 <= 16;
            }
            else
            {
                _loc_4 = this.sizePerVertex + param2 <= 16;
            }
            return _loc_4;
        }// end function

        public function addVertexData(param1:int, param2:int, param3:Data3dInfo, param4:Boolean) : int
        {
            var _loc_7:Data3dInfo = null;
            var _loc_8:String = null;
            if (param4 && this.isSingle && this.sizePerVertex > 0)
            {
                throw new Error("error in FrVertexBuffer3D.as");
            }
            var _loc_5:* = this.bufferVoMap[param1];
            var _loc_6:* = "float" + param2;
            if (_loc_5 != null)
            {
                _loc_8 = _loc_5.format;
                if (param3)
                {
                    _loc_7 = new Data3dInfo(this.vertexVector, this.sizePerVertex, _loc_5.offset, _loc_8);
                    this.vertexVector = this.insertData(param2, _loc_7, param3);
                    this.setOtherOffsets(_loc_5.size, param2, _loc_5.offset);
                }
                _loc_5.format = _loc_6;
                _loc_5.size = param2;
                this.sizePerVertex = this.sizePerVertex - int(_loc_8.charAt(5)) + param2;
                return _loc_5.offset;
            }
            else
            {
                if (param3)
                {
                    _loc_7 = new Data3dInfo(this.vertexVector, this.sizePerVertex, this.sizePerVertex, "float0");
                    this.vertexVector = this.insertData(param2, _loc_7, param3);
                }
                _loc_5 = new BufferVo(this, param1);
                _loc_5.format = _loc_6;
                _loc_5.offset = this.sizePerVertex;
                _loc_5.size = param2;
                this.sizePerVertex = this.sizePerVertex + param2;
                this.bufferVoMap[param1] = _loc_5;
            }
            return _loc_5.offset;
        }// end function

        private function setOtherOffsets(param1:int, param2:int, param3:int) : void
        {
            var _loc_5:Object = null;
            var _loc_6:BufferVo = null;
            if (param1 == param2)
            {
                return;
            }
            var _loc_4:* = param2 - param1;
            for (_loc_5 in this.bufferVoMap)
            {
                
                _loc_6 = this.bufferVoMap[_loc_5];
                if (_loc_6.offset > param3)
                {
                    _loc_6.offset = _loc_6.offset + _loc_4;
                }
            }
            return;
        }// end function

        public function insertData(param1:int, param2:Data3dInfo, param3:Data3dInfo = null) : Vector.<Number>
        {
            var _loc_14:int = 0;
            var _loc_4:* = param2.data;
            var _loc_5:* = param2.dataPerSize;
            var _loc_6:* = param2.dataOffset;
            var _loc_7:* = param2.dataFormat;
            var _loc_8:* = int(_loc_7.charAt(5));
            var _loc_9:* = param3.data;
            var _loc_10:* = param3.dataPerSize;
            var _loc_11:* = param3.dataOffset;
            var _loc_12:* = param3.dataFormat;
            var _loc_13:* = int(_loc_12.charAt(5));
            if (_loc_5 == 0)
            {
                if (_loc_10 == param1 && _loc_13 == param1)
                {
                    return _loc_9;
                }
                _loc_14 = _loc_9.length / _loc_10;
                return this.createNewVect(param1, _loc_14, param2, param3);
            }
            else
            {
                if (_loc_8 == param1)
                {
                    return this.replaceOldVect(param2, param3);
                }
                _loc_14 = _loc_4.length / _loc_5;
                return this.createNewVect(param1, _loc_14, param2, param3);
            }
        }// end function

        private function replaceOldVect(param1:Data3dInfo, param2:Data3dInfo = null) : Vector.<Number>
        {
            var _loc_13:int = 0;
            var _loc_14:int = 0;
            var _loc_3:* = param1.data;
            var _loc_4:* = param1.dataPerSize;
            var _loc_5:* = param1.dataOffset;
            var _loc_6:* = param1.dataFormat;
            var _loc_7:* = int(_loc_6.charAt(5));
            var _loc_8:* = param2.data;
            var _loc_9:* = param2.dataPerSize;
            var _loc_10:* = param2.dataOffset;
            var _loc_11:* = param2.dataFormat;
            var _loc_12:* = int(_loc_11.charAt(5));
            var _loc_15:* = _loc_3.length / _loc_4;
            var _loc_16:int = 0;
            var _loc_17:int = 0;
            while (_loc_16 < _loc_15)
            {
                
                _loc_13 = _loc_16 * _loc_4 + _loc_5;
                _loc_14 = _loc_16 * _loc_9 + _loc_10;
                _loc_17 = 0;
                while (_loc_17 < _loc_7)
                {
                    
                    if (_loc_17 >= _loc_12)
                    {
                        _loc_3[_loc_13 + _loc_17] = 1;
                    }
                    else
                    {
                        _loc_3[_loc_13 + _loc_17] = _loc_8[_loc_14 + _loc_17];
                    }
                    _loc_17++;
                }
                _loc_16++;
            }
            return _loc_3;
        }// end function

        private function createNewVect(param1:int, param2:int, param3:Data3dInfo, param4:Data3dInfo = null) : Vector.<Number>
        {
            var _loc_15:int = 0;
            var _loc_16:int = 0;
            var _loc_17:int = 0;
            var _loc_18:Vector.<Number> = null;
            var _loc_19:int = 0;
            var _loc_20:int = 0;
            var _loc_21:int = 0;
            var _loc_5:* = param3.data;
            var _loc_6:* = param3.dataPerSize;
            var _loc_7:* = param3.dataOffset;
            var _loc_8:* = param3.dataFormat;
            var _loc_9:* = int(_loc_8.charAt(5));
            var _loc_10:* = param4.data;
            var _loc_11:* = param4.dataPerSize;
            var _loc_12:* = param4.dataOffset;
            var _loc_13:* = param4.dataFormat;
            var _loc_14:* = int(_loc_13.charAt(5));
            _loc_17 = _loc_6 - _loc_9 + param1;
            _loc_18 = new Vector.<Number>(param2 * _loc_17);
            _loc_15 = 0;
            while (_loc_15 < param2)
            {
                
                _loc_16 = 0;
                _loc_19 = _loc_15 * _loc_17;
                _loc_20 = _loc_15 * _loc_6;
                while (_loc_16 < _loc_7)
                {
                    
                    _loc_18[_loc_19 + _loc_16] = _loc_5[_loc_20 + _loc_16];
                    _loc_16++;
                }
                _loc_16 = 0;
                _loc_19 = _loc_15 * _loc_17 + _loc_7;
                _loc_20 = _loc_15 * _loc_11 + _loc_12;
                while (_loc_16 < param1)
                {
                    
                    if (_loc_16 >= _loc_14)
                    {
                        _loc_18[_loc_19 + _loc_16] = 1;
                    }
                    else
                    {
                        _loc_18[_loc_19 + _loc_16] = _loc_10[_loc_20 + _loc_16];
                    }
                    _loc_16++;
                }
                _loc_16 = 0;
                _loc_19 = _loc_15 * _loc_17 + _loc_7 + param1;
                _loc_20 = _loc_15 * _loc_6 + _loc_7 + _loc_9;
                _loc_21 = _loc_6 - (_loc_7 + _loc_9);
                while (_loc_16 < _loc_21)
                {
                    
                    _loc_18[_loc_19 + _loc_16] = _loc_5[_loc_20 + _loc_16];
                    _loc_16++;
                }
                _loc_15++;
            }
            return _loc_18;
        }// end function

        final public function get vertexVector() : Vector.<Number>
        {
            if (!this._vertexVector)
            {
                this._vertexVector = new Vector.<Number>;
                if (this._vertexBytes)
                {
                    this._vertexBytes.position = 0;
                    while (this._vertexBytes.bytesAvailable)
                    {
                        
                        this._vertexVector.push(this._vertexBytes.readFloat());
                    }
                }
            }
            return this._vertexVector;
        }// end function

        final public function set vertexVector(param1:Vector.<Number>) : void
        {
            if (param1 != this._vertexVector)
            {
                this._vertexVector = param1;
                this.toUpdate();
            }
            return;
        }// end function

        public function dispose(param1:Boolean = false) : void
        {
            if (this.vertexBuffer)
            {
                this.vertexBuffer.dispose();
            }
            this.vertexBuffer = null;
            this._vertexBytes = null;
            this._vertexVector = null;
            var _loc_2:String = null;
            this._parentFrSurface = null;
            return;
        }// end function

        public function contextEvent(param1:Context3D) : Boolean
        {
            var _loc_2:int = 0;
            if (!this._needUpdate)
            {
                return true;
            }
            if (this.vertexBuffer)
            {
                this.vertexBuffer.dispose();
                this.vertexBuffer = null;
            }
            if (this._vertexVector)
            {
                _loc_2 = this._vertexVector.length / this.sizePerVertex;
                this.vertexBuffer = param1.createVertexBuffer(_loc_2, this.sizePerVertex);
                this.vertexBuffer.uploadFromVector(this._vertexVector, 0, _loc_2);
                this._needUpdate = false;
                return true;
            }
            if (this._vertexBytes && this._vertexBytes.length > 0)
            {
                _loc_2 = this._vertexBytes.length / 4 / this.sizePerVertex;
                this.vertexBuffer = param1.createVertexBuffer(_loc_2, this.sizePerVertex);
                this.vertexBuffer.uploadFromByteArray(this._vertexBytes, 0, 0, _loc_2);
                this._needUpdate = false;
                return true;
            }
            return false;
        }// end function

    }
}
